/**
 *Copyright (c) 2024 watereyes
 * workflow is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan
 * PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *          http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */
package com.koron.workflow.common.aop;

import com.google.common.base.Objects;
import com.google.gson.Gson;
import com.koron.workflow.common.annotation.CaseUser;
import com.koron.workflow.common.bean.StaffBean;
import com.koron.workflow.common.util.RedisUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.swan.bean.MessageBean;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

@Component
@Aspect
public class LoginAOP {

    /**
     * 过期时间
     */
    @Value("${token.expireTime}")
    private String EXPIRE_TIME;

    // 切点
    private static final String POINT_CUT_INCLUDE = "execution(public * com.koron..controller.*.*(..))";
    
    @Pointcut(POINT_CUT_INCLUDE)
    public void pointCut() {
    	
    }
    
    // 过滤请求
    private String[] filterUrls = new String[]{"login.htm", "updateWorkFlowCandidateSSO.htm", "workFlowDesignSSO.htm", "logout.htm", "/process/start.htm", "/process/submit.htm", "/process/view.htm", "/process/history.htm", "/process/list.htm", "/process/define.htm", "/mobile/historyView.htm", "/mobile/approvalView.htm", "/process/suspend.htm", "/process/recovery.htm", "/process/deleteProcess.htm"};

    @Around(value = "pointCut()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        Object obj = MessageBean.create(10000, "没有获取到登录信息", String.class);
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();
        // 过滤掉请求
        for (String url : filterUrls) {
            if (request.getRequestURI().indexOf(url) > -1) {
                return proceedingJoinPoint.proceed();
            }
        }
        String token = request.getParameter("token");
        if (StringUtils.isEmpty(token)) {
            token = request.getHeader("token");
            if (StringUtils.isEmpty(token) || Objects.equal(token, "null")) {
                Cookie[] cookies = request.getCookies();
                if (cookies != null && cookies.length > 0) {
                    for (Cookie cookie : cookies) {
                        if ("token".equals(cookie.getName())) {
                            token = cookie.getValue();
                            break;
                        }
                    }
                }
            }
        }
        // 判断token是否有效
        if (!StringUtils.isEmpty(token) && RedisUtils.hasKey(token)) {
            // 更新过期时间
            RedisUtils.expire(token, Integer.parseInt(EXPIRE_TIME));
            MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
            Method method = methodSignature.getMethod();
            Object[] args = proceedingJoinPoint.getArgs();
            Parameter[] parameters = method.getParameters();
            if (parameters != null && parameters.length > 0) {
                CaseUser caseUser;
                int i = 0;
                for (Parameter param : parameters) {
                    caseUser = param.getAnnotation(CaseUser.class);
                    if (caseUser != null && param.getType().equals(StaffBean.class)) {
                        String val = RedisUtils.get(token);
                        if (val == null) {
                            return obj;
                        }
                        // 给形参赋值
                        args[i] = new Gson().fromJson(val.toString(), StaffBean.class);
                        return proceedingJoinPoint.proceed(args);
                    }
                    i++;
                }
            }
            obj = proceedingJoinPoint.proceed();
        }
        return obj;
    }
}
